package com.xcity.game.guild;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xcity.config.ConfigEx;
import com.xcity.db.entity.Guild;
import com.xcity.db.entity.GuildApply;
import com.xcity.db.entity.GuildMember;
import com.xcity.db.entity.Player;
import com.xcity.db.mapper.GuildApplyMapper;
import com.xcity.db.mapper.GuildMapper;
import com.xcity.db.mapper.GuildMemberMapper;
import com.xcity.game.chat.ChatMessage;
import com.xcity.game.common.Cause;
import com.xcity.game.common.MessageConst;
import com.xcity.game.event.GameEvents;
import com.xcity.game.guild.gevent.GuildEvent;
import com.xcity.game.guild.operation.GuildDisbandOperation;
import com.xcity.game.guild.operation.GuildTransferOperation;
import com.xcity.game.guild.template.GuildDonateTemplate;
import com.xcity.game.guild.template.GuildExpTemplate;
import com.xcity.game.player.PlayerService;
import com.xcity.game.player.cache.PlayerCacheService;
import com.xcity.pomelo.PomeloRoute;
import com.xcity.pomelo.push.ChatPush;
import com.xcity.pomelo.push.SyncPush;
import com.xcity.pomelo.push.sync.CustomSync;
import com.xcity.pomelo.push.sync.IntSync;
import com.xcity.pomelo.push.sync.LongSync;
import com.xcity.pomelo.request.AgreeApplyRequest;
import com.xcity.pomelo.request.ApplyJoinRequest;
import com.xcity.pomelo.request.CreateGuildRequest;
import com.xcity.pomelo.request.GetApplyListRequest;
import com.xcity.pomelo.request.GuildDetailRequest;
import com.xcity.pomelo.request.GuildDonateRequest;
import com.xcity.pomelo.request.GuildEventListRequest;
import com.xcity.pomelo.request.GuildGetRewardRequest;
import com.xcity.pomelo.request.GuildKickRequest;
import com.xcity.pomelo.request.GuildListRequest;
import com.xcity.pomelo.request.GuildMemberListRequest;
import com.xcity.pomelo.request.GuildSetAllRequest;
import com.xcity.pomelo.request.GuildSetDutyRequest;
import com.xcity.pomelo.request.GuildTransferRequest;
import com.xcity.pomelo.request.GuildViewRewardRequest;
import com.xcity.pomelo.request.QuitGuildRequest;
import com.xcity.pomelo.request.SetIconRequest;
import com.xcity.pomelo.request.SetJoinLvlRequest;
import com.xcity.pomelo.request.SetJoinTypeRequest;
import com.xcity.pomelo.request.SetSloganRequest;
import com.xcity.pomelo.request.GuildViewDonateRequest;
import com.xcity.pomelo.request.ViewNetGuildRequest;
import com.xcity.pomelo.response.AgreeApplyResponse;
import com.xcity.pomelo.response.ApplyJoinResponse;
import com.xcity.pomelo.response.CreateGuildResponse;
import com.xcity.pomelo.response.GetApplyListResponse;
import com.xcity.pomelo.response.GuildDetailResponse;
import com.xcity.pomelo.response.GuildDonateResponse;
import com.xcity.pomelo.response.GuildEventListResponse;
import com.xcity.pomelo.response.GuildGetRewardResponse;
import com.xcity.pomelo.response.GuildInfoSync;
import com.xcity.pomelo.response.GuildKickResponse;
import com.xcity.pomelo.response.GuildListResponse;
import com.xcity.pomelo.response.GuildMemberListResponse;
import com.xcity.pomelo.response.GuildSetAllResponse;
import com.xcity.pomelo.response.GuildSetDutyResponse;
import com.xcity.pomelo.response.GuildViewRewardResponse;
import com.xcity.pomelo.response.HintResponse;
import com.xcity.pomelo.response.QuitGuildResponse;
import com.xcity.pomelo.response.Response;
import com.xcity.pomelo.response.SetIconResponse;
import com.xcity.pomelo.response.SetJoinLvlResponse;
import com.xcity.pomelo.response.SetJoinTypeResponse;
import com.xcity.pomelo.response.SetSloganResponse;
import com.xcity.pomelo.response.GuildViewDonateResponse;
import com.xcity.pomelo.response.ViewNetGuildResponse;
import com.xcity.util.BackDoorHandler;
import com.xcity.util.DBUtils;
import com.xcity.util.RandomUtils;

import gnu.trove.map.hash.TIntObjectHashMap;
import naga.x.App;
import naga.x.common.Updatable;
import naga.x.event.Event;
import naga.x.event.EventListener;
import naga.x.game.template.TemplateService;
import naga.x.game.time.TimeUpdater;
import naga.x.net.Session;
import naga.x.net.annotation.OPHandler;
import naga.x.net.impl.pomelo.annotation.PomeloOP;
import naga.x.service.Service;
import naga.x.service.ServiceException;
import naga.x.util.KeywordsManager;
import naga.x.util.StringUtils;
/**
 * 公会服务<br />
 * 对gid2guild和pid2member两个集合操作<br />
 * 登录时读入内存 shutdown时存库
 * @author shipeng.zhu
 *
 */
@OPHandler
public class GuildService implements Service, EventListener, Updatable{
	
	public static final Logger LOG = LoggerFactory.getLogger(GuildService.class);

	public static int NEED_VIP = 0;//创建公会需要VIP等级
	public static int NEED_STONE = 500;//创建公会需要花费钻石
	public static int GUILD_NAME_LENGTH = 12;//创建公会名字长度
	public static int GUILD_SLOGAN_LENGTH = 70;//公会公告长度
	public static int GUILD_FLAG_TYPE1_COUNT = 6;//公会图案样式1种类
	public static int GUILD_FLAG_TYPE2_COUNT = 18;//公会图案样式2种类
	public static int[] JOIN_LEVEL_LIMITS = new int[]{0, 70, 60, 50};//入会等级限制
	/**
	 * 缓存公会数据
	 */
	protected ConcurrentHashMap<Long, Guild> gid2guild = new ConcurrentHashMap<Long, Guild>();
	
	/**
	 * 缓存最近MAX_CACHE_RESULT次的根据名字查找公会的结果数据
	 */
	protected ConcurrentHashMap<String, List<Guild>> name2guildList = new ConcurrentHashMap<String, List<Guild>>(8);
	public static int MAX_CACHE_GUILD_LIST_RESULT = 30;
	
	/**
	 * 缓存最近一次默认公会的结果数据
	 */
	protected List<Guild> cacheFindGuildList;// = new ArrayList<Guild>();
	protected long lastLoadGuildListTime = 0L;
	public static int GUILD_LIST_REFRESH_CD = 15 * 60 * 1000;//15分钟才重新从数据库里取一次cache
	
	/**
	 * 缓存玩家成员数据 有增减和玩家换会的话要更新到数据库
	 */
	protected ConcurrentHashMap<Long, GuildMember> pid2member = new ConcurrentHashMap<Long, GuildMember>();
	
	/**
	 * 缓存玩家成员列表数据 只缓存有限个公会的成员信息
	 */
	protected ConcurrentHashMap<Long, List<GuildMember>> gid2memberList = new ConcurrentHashMap<Long, List<GuildMember>>(16);
	
	protected ConcurrentHashMap<Long, GuildChannel> gid2guildchannel = new ConcurrentHashMap<>();
	
	public static int MAX_CACHE_MEMBER_LIST_RESULT = 15;
	
	public static int MEMBER_DUTY_TYPE_CHAIRMAN = 100;//职位类型 会长
	public static int MEMBER_DUTY_TYPE_OFFICIAL = 50;//副会长
	public static int MEMBER_DUTY_TYPE_MEMBER = 0;//普通成员
	
	public static int MAX_MEMBER_COUNT = 50;//公会最大人数
	public static int MAX_OFFICIAL_COUNT = 2;//最大副会长层人数
	
	public static int JOIN_GUILD_CD_MILLISECOND = BackDoorHandler.CHEAT_ENABLE? 1 * 1000 : 8 * 3600 * 1000;
	
	public static int BASE_REWARD = 50000;
	
	protected KeywordsManager badwordsFilter;
	
	protected int[] guildTotalExp;//index -> 升到index + 2级需要的总经验
	
	protected List<GuildExpTemplate> expList;
	protected TIntObjectHashMap<GuildDonateTemplate> type2donateTemp = new TIntObjectHashMap<GuildDonateTemplate>();
	
	protected long lastPrintCacheSize = 0L;
	
	@Override
	public void startup() throws ServiceException {
		badwordsFilter = ((ConfigEx) App.getApp().getConfig()).getBadwordsFilter();
		initTemp();
		App.getApp().getEventManager().register(this);
		App.getApp().getUpdater().addAsync(this);
	}
	
	public void initTemp(){
		expList = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(GuildExpTemplate.class);
		expList.sort(new Comparator<GuildExpTemplate>() {
			@Override
			public int compare(GuildExpTemplate o1, GuildExpTemplate o2) {
				return o1.getLevel() - o2.getLevel();
			}
		});
		
		guildTotalExp = new int[expList.size()];
		int total = 0;
		for(int i = 0, size = expList.size(); i < size; i++){
			guildTotalExp[i] = total + expList.get(i).getExp();
			total = guildTotalExp[i];
		}
		type2donateTemp.clear();
		List<GuildDonateTemplate> donateList = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(GuildDonateTemplate.class);
		for(int i = 0; i < donateList.size(); i++){
			GuildDonateTemplate tmp = donateList.get(i);
			if(tmp.getMax() > 0){
				type2donateTemp.put(tmp.getType(), tmp);
			}
		}
		
	}

	@Override
	public void shutdown() throws ServiceException {
		for(Guild guild : gid2guild.values()){
			DBUtils.update(guild, GuildMapper.class);
		}
		
		for(GuildMember guildMember : pid2member.values()){
			DBUtils.update(guildMember, GuildMemberMapper.class);
		}
	}

	@Override
	public String getId() {
		return getClass().getName();
	}
	@Override
	public int[] getEventTypes() {
		return new int[]{
				GameEvents.EVENT_PLAYER_LOGIN,
				GameEvents.EVENT_PLAYER_LOGOUT,
		};
	}

	@Override
	public void handleEvent(Event event) {
		switch (event.getType()) {
		case GameEvents.EVENT_PLAYER_LOGIN:
			playerLogin(event.getParameter());
			break;
		case GameEvents.EVENT_PLAYER_LOGOUT:
			playerLogout(event.getParameter());
			break;
		default:
			break;
		}
	}

	public void playerLogin(Player player){
		if(!pid2member.containsKey(player.getId())){//内存里没有
			GuildMember member = loadGuildMember(player.getId());
			if(member != null){//数据库里没有
				Guild guild = findGuildById(member.getGuildid());
				if(guild != null){
					if(gid2guildchannel.containsKey(guild.getId())){
						gid2guildchannel.get(guild.getId()).join(player);
					}else{
						gid2guildchannel.put(guild.getId(), new GuildChannel(player));
					}
				}else{
					//TODO 有member 没公会
				}
			}
		}else{
			GuildMember member = pid2member.get(player.getId());
			if(member != null){
				Guild guild = findGuildById(member.getGuildid());
				if(guild != null){
					if(gid2guildchannel.containsKey(guild.getId())){
						gid2guildchannel.get(guild.getId()).join(player);
					}else{
						gid2guildchannel.put(guild.getId(), new GuildChannel(player));
					}
				}else{
					//TODO 有member 没公会
				}
			}
		}
	}
	
	public void playerLogout(Player player){
		GuildMember member = pid2member.get(player.getId());
		if(member != null){//内存里没有
			DBUtils.update(member, GuildMemberMapper.class);
			Guild guild = findGuildById(member.getGuildid());
			if(guild != null){
				if(gid2guildchannel.containsKey(guild.getId())){
					gid2guildchannel.get(guild.getId()).leave(player);
				}
			}
		}
	}
	
	public GuildMember getGuildMember(long pid){
		return pid2member.get(pid);
	}
	
	public Guild findGuildByPlayerId(long pid){
		GuildMember m = pid2member.get(pid);
		if(m == null){
			return null;
		}
		return findGuildById(m.getGuildid());
	}
	/**
	 * 移除gid2guild中的guild
	 * 移除gid2memberList中的memberlist
	 * 如果成员在线发送同步公会ID
	 */
	public Guild removeGuildByGuildId(long gid){
		List<GuildMember> memberList = gid2memberList.remove(gid);
		if(memberList != null){
			PlayerService pcs = App.getApp().getServiceManager().get(PlayerService.class);
			for(int i = 0, size = memberList.size(); i < size; i++){
				Player player = pcs.getOnlinePlayer(memberList.get(i).getId());
				if(player != null){
					player.send(new CustomSync(SyncPush.SYNC_GUILD_INFO, new GuildInfoSync(0, null)));
				}			
			}
		}
		tryRemoveFromGuildListCache(gid);
		for(int i = cacheFindGuildList.size() - 1; i > -1; i--){
			if(cacheFindGuildList.get(i).getId() == gid){
				cacheFindGuildList.remove(i);
				break;
			}
		}
		return gid2guild.remove(gid);
	}
	
	/**
	 * 加入公会时 把member加入缓存
	 */
	public void tryAddToMemberListCache(long gid, GuildMember guildMember){
		List<GuildMember> memberList = gid2memberList.get(gid);
		if(memberList != null){
			boolean needPutInCache = true;
			for(int i = 0, size = memberList.size(); i < size; i++){
				if(memberList.get(i).getId() == guildMember.getId()){
					needPutInCache = false;
					break;
				}
			}
			if(needPutInCache){
				memberList.add(guildMember);
			}
		}
	}
	
	/**
	 * 离开公会时 把member移出缓存
	 */
	public void tryRemoveFromMemberListCache(long gid, long removeId){
		List<GuildMember> memberList = gid2memberList.get(gid);
		if(memberList != null){
			for(int i = 0, size = memberList.size(); i < size; i++){
				if(memberList.get(i).getId() == removeId){
					memberList.remove(i);
					break;
				}
			}
		}
	}
	
	
	/**
	 * 创建公会时加入缓存
	 * @param newGuild
	 */
	public void tryAddToGuildListCache(Guild newGuild){
		for(String name : name2guildList.keySet()){
			if(newGuild.getName().indexOf(name) > -1){
				List<Guild> list = name2guildList.get(name);
				if(list != null){
					for(int i = 0, size = list.size(); i < size; i++){
						if(list.get(i).getId() == newGuild.getId()){
							list.remove(i);
							break;
						}
					}
					if(list.size() < 50){
						list.add(newGuild);
					}
				}
			}
		}
	}
	/**
	 * 解散公会时移出缓存
	 * @param name
	 * @param gid
	 */
	public void tryRemoveFromGuildListCache(long gid){
		for(List<Guild> list : name2guildList.values()){
			for(int i = 0, size = list.size(); i < size; i++){
				if(list.get(i).getId() == gid){
					list.remove(i);
					break;
				}
			}
		}
	}
	
	/**
	 * read
	 */
	public GuildMember loadGuildMember(long pid){
		GuildMember member = DBUtils.find(pid, GuildMemberMapper.class);
		if(member == null){
			return null;
		}
		member.init();
		pid2member.put(pid, member);
		//把缓存中的member 替换成在线的
		tryRemoveFromMemberListCache(member.getGuildid(), pid);
		tryAddToMemberListCache(member.getGuildid(), member);
		return member;
	}
	
	/**
	 * read
	 */
	public Guild loadGuild(long gid){
		Guild ret = DBUtils.find(gid, GuildMapper.class);
		if(ret == null){
			return null;
		}
		ret.init();
		gid2guild.put(ret.getId(), ret);
		return ret;
	}
	
	private Guild getGuild(long gid){
		return gid2guild.get(gid);
	}
	/**
	 * 根据guildid查找guild
	 * @param guildId
	 * @return Guild or null
	 */
	public Guild findGuildById(long id){
		Guild g = getGuild(id);
		if(g == null){
			g = loadGuild(id);
		}
		return g;
	}
	
	@PomeloOP(PomeloRoute.GUILD_CREATE)
	protected void requestCreateGuild(Session session, CreateGuildRequest req){
		Player player = session.getClient();
		if(player.getVipLvl() < NEED_VIP){
			player.send(new HintResponse(req.getSerial(), MessageFormat.format(MessageConst.GUILD_NEED_VIP, NEED_VIP)));
			return;
		}
		String name = req.getName();
		String err = checkGuildName(name);
		if(err != null){
			player.send(new HintResponse(req.getSerial(), err));
			return;
		}
		int type1 = req.getType1();
		int type2 = req.getType2();
		//findGuildsByName
		int joinLvl = req.getJoinLvl();
		if(joinLvl >= JOIN_LEVEL_LIMITS.length || joinLvl < 0){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_JOIN_LVL_ERR));
			return;
		}
		
		String slogan = req.getSlogan();
		err = checkSlogan(slogan);
		if(err != null){
			player.send(new HintResponse(req.getSerial(), err));
			return;
		}
		int joinType = req.getJoinType();
		if(joinType != Guild.JOIN_TYPE_FREE && joinType != Guild.JOIN_TYPE_NONE_SHALL_PASS && joinType != Guild.JOIN_TYPE_NEED_APPLY){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_SET_WRONG_TYPE));
			return;
		}
		slogan = badwordsFilter.filterBadWords(slogan);
		
		GuildMember member = null;
		if(pid2member.containsKey(player.getId())){
			member = pid2member.get(player.getId());
			Guild guild = findGuildById(member.getGuildid());
			if(guild != null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_HAVE_GUILD));
				return;
			}
		}
		
		if(NEED_STONE > 0){
			if(!player.costStone(NEED_STONE, Cause.CREAT_GUILD)){
				player.send(new HintResponse(req.getSerial(), MessageConst.STONE_NOT_ENOUTH));
				return;
			}
		}
		//create guild
		Guild guild = new Guild(player.getId(), name);
		guild.setFlag(type1 << 8 | type2);
		guild.setSlogan(slogan);
		guild.setJoinLvl((byte) joinLvl);
		guild.setJoinType((byte) joinType);
		guild.setMemCount(1);
		gid2guild.put(guild.getId(), guild);
		DBUtils.save(guild, GuildMapper.class);
		tryAddToGuildListCache(guild);
		//处理member
		boolean needSave = false;
		if(member == null){
			member = new GuildMember(player.getId());
			pid2member.put(player.getId(), member);
			needSave = true;
		}
		member.setGuildid(guild.getId());
		if(player.isOnline()){
			if(gid2guildchannel.containsKey(guild.getId())){
				gid2guildchannel.get(guild.getId()).join(player);
			}else{
				gid2guildchannel.put(guild.getId(), new GuildChannel(player));
			}
		}
		member.setDuty(MEMBER_DUTY_TYPE_CHAIRMAN);
		if(needSave){
			DBUtils.save(member, GuildMemberMapper.class);
		}else{
			DBUtils.update(member, GuildMemberMapper.class);
		}
		//把申请取消
		DBUtils.delete(GuildApplyMapper.STATEMENT_DELETE_BY_APPLICANT, player.getId());
		player.send(new CreateGuildResponse(req.getSerial(), guild.getId()));
		LOG.info("[GUILD_CREATE]PID[{}]GID[{}]FLAG[{}]JOINTYPE[{}]JOINLVL[{}]", player.getId(), guild.getId(), guild.getFlag(), guild.getJoinType(), guild.getJoinLvl());
	}

	@PomeloOP(PomeloRoute.GUILD_QUIT)
	protected void requestQuitGuild(Session session, QuitGuildRequest req){
		Player player = session.getClient();
		GuildMember guildMember = pid2member.get(player.getId());
		if(guildMember != null){
			if(guildMember.getGuildid() > 0){
				if(guildMember.getDuty() == MEMBER_DUTY_TYPE_CHAIRMAN){
					//是会长
					int count = DBUtils.select(GuildMemberMapper.STATEMENT_COUNT_MEMBER_BY_GUILD, guildMember.getGuildid());
					if(count > 1){
						player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_QUIT_MUST_EMPTY));
						return;
					}else{
						//解散公会
						new GuildDisbandOperation(player, guildMember, guildMember.getGuildid(), req.getSerial(), 60000, MessageConst.GUILD_QUIT_CONFIRM_DISBAND).send();
						return;
					}
				}else{
					long gid = guildMember.getGuildid();
					guildMember.reset();
					if(gid2guildchannel.containsKey(gid)){
						gid2guildchannel.get(gid).leave(player);
					}
					DBUtils.update(guildMember, GuildMemberMapper.class);
					Guild guild = findGuildById(gid);
					if(guild != null){
						guild.setMemCount(guild.getMemCount() - 1);
						guild.getGevent().addNewGuildEvents(GuildEvent.EVENT_TYPE_QUIT, player.getId(), 0);
						tryRemoveFromMemberListCache(guild.getId(), player.getId());
					}
					player.send(new QuitGuildResponse(req.getSerial(), guild.getId()));
					LOG.info("[GUILD_QUIT]PID[{}]GID[{}]", player.getId(), gid);
					sendSyncForGuildChannel(player.getId(), guild.getId(), GuildChannel.GUILD_MEMBER_CHANGE_SYNC | GuildChannel.GUILD_EVENT_CHANGE_SYNC | GuildChannel.GUILD_DETAIL_CHANGE_SYNC);
					return;
				}
			}
		}
		player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));

	}
	

	/**
	 * 申请入会
	 */
	@PomeloOP(PomeloRoute.GUILD_APPLY)
	protected void requestApplyJoin(Session session, ApplyJoinRequest req){
		Player player = session.getClient();
		GuildMember guildMember = pid2member.get(player.getId());
		if(guildMember != null){
			if(guildMember.getGuildid() > 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_HAVE_GUILD));
				return;
			}

			Date date = guildMember.getCreateTime();
			long endTime = date.getTime() + JOIN_GUILD_CD_MILLISECOND;
			if(endTime >= TimeUpdater.getInstance().now()){
				int needSecond = (int) ((endTime - TimeUpdater.getInstance().now()) / 1000);
				if(needSecond > 3600){
					int needHour = needSecond / 3600;
					int needMinute = needSecond / 60 % 60;
					player.send(new HintResponse(req.getSerial(), MessageFormat.format(MessageConst.GUILD_JOIN_NEXT_HOUR, needHour, needMinute)));
				}else{
					int needMinute = needSecond / 60;
					if(needMinute <= 0){
						needMinute = 1;
					}
					player.send(new HintResponse(req.getSerial(), MessageFormat.format(MessageConst.GUILD_JOIN_NEXT_MINUTE, needMinute)));
				}
				return;
			}
		}
		long target = req.getTarget();
		Guild guild = findGuildById(target);
		if(guild == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_GUILD));
			return;
		}
		
		if(guild.getJoinType() == Guild.JOIN_TYPE_NONE_SHALL_PASS){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_JOIN_REFUSE_ALL));
			return;
		}
		
		int count = DBUtils.select(GuildMemberMapper.STATEMENT_COUNT_MEMBER_BY_GUILD, target);
		if(count >= MAX_MEMBER_COUNT){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_JOIN_FULL));
			return;
		}
		
		int lvlLimit = getJoinNeedLvlByGuild(guild);
		if(player.getLevel() < lvlLimit){
			player.send(new HintResponse(req.getSerial(), MessageFormat.format(MessageConst.GUILD_JOIN_NEED_LVL, lvlLimit)));
			return;
		}
		
		if(guild.getJoinType() == Guild.JOIN_TYPE_FREE){
			boolean needSave = false;
			if(guildMember == null){
				guildMember = new GuildMember(player.getId());
				needSave = true;
			}
			guildMember.setGuildid(target);
			if(player.isOnline()){
				if(gid2guildchannel.containsKey(guild.getId())){
					gid2guildchannel.get(guild.getId()).join(player);
				}else{
					gid2guildchannel.put(guild.getId(), new GuildChannel(player));
				}
			}
			guildMember.setDuty(MEMBER_DUTY_TYPE_MEMBER);
			if(needSave){
				pid2member.put(player.getId(), guildMember);
				DBUtils.save(guildMember, GuildMemberMapper.class);
			}else{
				guildMember.setCreateTime(new Date());
				DBUtils.update(guildMember, GuildMemberMapper.class);
			}
			
			//需要加入缓存 客户端刷新用
			tryAddToMemberListCache(target, guildMember);
			//把申请取消
			DBUtils.delete(GuildApplyMapper.STATEMENT_DELETE_BY_APPLICANT, player.getId());
			player.send(new ApplyJoinResponse(req.getSerial(), guild));
			//公会人数量++
			guild.setMemCount(guild.getMemCount() + 1);
			guild.getGevent().addNewGuildEvents(GuildEvent.EVENT_TYPE_JOIN, player.getId(), 0);
			LOG.info("[GUILD_JOIN]PID[{}]GID[{}]", player.getId(), guild.getId());

			sendSyncForGuildChannel(player.getId(), guild.getId(), GuildChannel.GUILD_MEMBER_CHANGE_SYNC | GuildChannel.GUILD_EVENT_CHANGE_SYNC | GuildChannel.GUILD_DETAIL_CHANGE_SYNC);
			return;
		}
		//需要申请
		Object params = DBUtils.wrapParams("applicant", player.getId(), "guildId", guild.getId());
		int applyCount = DBUtils.select(GuildApplyMapper.STATEMENT_APPLY_COUNT_BY_PARAM, params);
		if(applyCount > 0){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_ALREADY_APPLY));
			return;
		}
		GuildApply apply = new GuildApply(player.getId(), target);
		DBUtils.save(apply, GuildApplyMapper.class);
		player.send(new ApplyJoinResponse(req.getSerial(), guild.getId()));
		sendSyncForGuildChannel(0, guild.getId(), GuildChannel.GUILD_APPLY_CHANGE_SYNC);
	}

	/**
	 * 获得申请列表
	 */
	@PomeloOP(PomeloRoute.GUILD_APPLY_LIST)
	protected void requestGetApplyList(Session session, GetApplyListRequest req){
		Player player = session.getClient();
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			if(member.getDuty() < MEMBER_DUTY_TYPE_OFFICIAL){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_VIEW));
				return;
			}
		}
		
		List<GuildApply> appliList = DBUtils.selectList(GuildApplyMapper.STATEMENT_FIND_BY_GUILD, guild.getId());
		player.send(new GetApplyListResponse(req.getSerial(), appliList));
	}

	@PomeloOP(PomeloRoute.GUILD_SET_SLOGAN)
	protected void requestSetSlogan(Session session, SetSloganRequest req){
		Player player = session.getClient();
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			if(member.getDuty() != MEMBER_DUTY_TYPE_CHAIRMAN){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_SET_SLOGAN));
				return;
			}
		}
		String slogan = req.getSlogan();
		String err = checkSlogan(slogan);
		if(err != null){
			player.send(new HintResponse(req.getSerial(), err));
			return;
		}
		slogan = badwordsFilter.filterBadWords(slogan);
		guild.setSlogan(slogan);
		player.send(new SetSloganResponse(req.getSerial(), slogan));
		LOG.info("[GUILD_SETSLOGAN]PID[{}]GID[{}]", player.getId(), guild.getId());

		//其他成员同步
		sendSyncForGuildChannel(player.getId(), guild.getId(), GuildChannel.GUILD_DETAIL_CHANGE_SYNC);
	}

	@PomeloOP(PomeloRoute.GUILD_SET_ICON)
	protected void requestSetIcon(Session session, SetIconRequest req){
		Player player = session.getClient();
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			if(member.getDuty() != MEMBER_DUTY_TYPE_CHAIRMAN){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_SET_ICON));
				return;
			}
		}
		int type1 = req.getType1();
		int type2 = req.getType2();
		guild.setFlag(type1 << 8 | type2);
		player.send(new SetIconResponse(req.getSerial(), type1, type2));
		LOG.info("[GUILD_SET]PID[{}]GID[{}]ICON[{}]", player.getId(), guild.getId(), guild.getFlag());
	}
	
	/**
	 * 设置入会限制类型
	 */
	@PomeloOP(PomeloRoute.GUILD_SET_JOINTYPE)
	protected void requestSetJoinType(Session session, SetJoinTypeRequest req){
		Player player = session.getClient();
		int type = req.getType();
		if(type != Guild.JOIN_TYPE_FREE && type != Guild.JOIN_TYPE_NONE_SHALL_PASS && type != Guild.JOIN_TYPE_NEED_APPLY){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_SET_WRONG_TYPE));
			return;
		}
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			if(member.getDuty() != MEMBER_DUTY_TYPE_CHAIRMAN){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_SET));
				return;
			}
		}
		guild.setJoinType((byte) type);
		player.send(new SetJoinTypeResponse(req.getSerial(), type));
		LOG.info("[GUILD_SET]PID[{}]GID[{}]JOINTYPE[{}]", player.getId(), guild.getId(), type);
	}
	
	@PomeloOP(PomeloRoute.GUILD_SET_JOINLVL)
	protected void requestSetJoinLvl(Session session, SetJoinLvlRequest req){
		Player player = session.getClient();
		int joinLvl = req.getJoinLvl();
		if(joinLvl >= JOIN_LEVEL_LIMITS.length || joinLvl < 0){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_JOIN_LVL_ERR));
			return;
		}
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			if(member.getDuty() != MEMBER_DUTY_TYPE_CHAIRMAN){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_SET));
				return;
			}
		}
		guild.setJoinLvl((byte) joinLvl);
		player.send(new SetJoinLvlResponse(req.getSerial(), joinLvl));
		LOG.info("[GUILD_SET]PID[{}]GID[{}]JOINLVL[{}]", player.getId(), guild.getId(), joinLvl);
	
	}
	/**
	 * 通过申请
	 */
	@PomeloOP(PomeloRoute.GUILD_AGREE_APPLY)
	protected void requestAgreeApply(Session session, AgreeApplyRequest req){
		Player player = session.getClient();
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			if(member.getDuty() < MEMBER_DUTY_TYPE_OFFICIAL){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_VIEW));
				return;
			}
		}
		
		int agree = req.getAgree();
		
		GuildApply apply = DBUtils.find(req.getAid(), GuildApplyMapper.class);
		if(apply == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_APPLY));
			return;
		}
		
		if(agree == 1){
			//同意
			PlayerCacheService pcs = App.getApp().getServiceManager().get(PlayerCacheService.class);
			Player applyPlayer = pcs.find(apply.getApplicant());
			if(applyPlayer == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_FOUND_APPLY_PLAYER));
				return;
			}

			boolean needSave = false;
			GuildMember guildMember = pid2member.get(applyPlayer.getId());
			if(guildMember == null){
				guildMember = loadGuildMember(applyPlayer.getId());
			}
			if(guildMember == null){
				guildMember = new GuildMember(applyPlayer.getId());
				needSave = true;
			}
			guildMember.setGuildid(guild.getId());
			if(applyPlayer.isOnline()){
				if(gid2guildchannel.containsKey(guild.getId())){
					gid2guildchannel.get(guild.getId()).join(applyPlayer);
				}else{
					gid2guildchannel.put(guild.getId(), new GuildChannel(applyPlayer));
				}
				applyPlayer.send(new CustomSync(SyncPush.SYNC_GUILD_INFO, new GuildInfoSync(guild.getId(), guild.getName())));
			}
			guildMember.setDuty(MEMBER_DUTY_TYPE_MEMBER);
			if(needSave){
				pid2member.put(applyPlayer.getId(), guildMember);
				DBUtils.save(guildMember, GuildMemberMapper.class);
			}else{
				guildMember.setCreateTime(new Date());
				DBUtils.update(guildMember, GuildMemberMapper.class);
			}
			//加入缓存
			tryAddToMemberListCache(guild.getId(), guildMember);
			
			DBUtils.delete(GuildApplyMapper.STATEMENT_DELETE_BY_APPLICANT, applyPlayer.getId());
			guild.setMemCount(guild.getMemCount() + 1);
			guild.getGevent().addNewGuildEvents(GuildEvent.EVENT_TYPE_JOIN, applyPlayer.getId(), 0);
			//TODO 下发成员信息
			player.send(new AgreeApplyResponse(req.getSerial(), guildMember, applyPlayer, req.getAid()));
			LOG.info("[GUILD_JOIN]PID[{}]GID[{}]", applyPlayer.getId(), guild.getId());

			sendSyncForGuildChannel(player.getId(), guild.getId(), GuildChannel.GUILD_MEMBER_CHANGE_SYNC | GuildChannel.GUILD_EVENT_CHANGE_SYNC | GuildChannel.GUILD_APPLY_CHANGE_SYNC | GuildChannel.GUILD_DETAIL_CHANGE_SYNC);
			return;
		}else{
			//拒绝
			DBUtils.delete(GuildApplyMapper.STATEMENT_DELETE_BY_ID, apply.getId());
			sendSyncForGuildChannel(player.getId(), guild.getId(), GuildChannel.GUILD_EVENT_CHANGE_SYNC);
		}
		player.send(new AgreeApplyResponse(req.getSerial(), req.getAid()));
	}

	/**
	 * 根据名字查询公会 不填名字则是随机取cache里的数据
	 */
	@PomeloOP(PomeloRoute.GUILD_LIST)
	protected void requestGuildList(Session session, GuildListRequest req){
		Player player = session.getClient();
		String name = req.getName();
		List<GuildApply> applyList = DBUtils.selectList(GuildApplyMapper.STATEMENT_FIND_BY_APPLICANT, player.getId());
		if(name == null || StringUtils.isEmpty(name)){
			List<Long> ids = new ArrayList<>(gid2guild.keySet());
			int maxSize = 50;
			if(ids.size() < maxSize){
				//cache不够数 从数据库取
				long now = TimeUpdater.getInstance().now();
				if(cacheFindGuildList == null || lastLoadGuildListTime + GUILD_LIST_REFRESH_CD < now){
					cacheFindGuildList = new ArrayList<Guild>();
					Object params = DBUtils.wrapParams("name", "%%", "limit", 50);
					List<Guild> tmpList = DBUtils.selectList(GuildMapper.STATEMENT_FIND_GUILD_BY_NAME, params);
					maxSize = tmpList.size();
					for(int i = 0; i < maxSize; i++){
						int index = RandomUtils.getRandomNum(0, tmpList.size() - 1);
						Guild remove = tmpList.remove(index);
						Guild cache = gid2guild.get(remove.getId());
						if(cache != null){
							cacheFindGuildList.add(cache);
						}else{
							cacheFindGuildList.add(remove);
						}
					}
					lastLoadGuildListTime = now;
				}
				player.send(new GuildListResponse(req.getSerial(), cacheFindGuildList, applyList));
				return;
			}else{
				List<Guild> retList = new ArrayList<Guild>();
				for(int i = 0; i < maxSize; i++){
					int index = RandomUtils.getRandomNum(0, ids.size() - 1);
					long id = ids.remove(index);
					Guild guild = gid2guild.get(id);
					retList.add(guild);
				}
				player.send(new GuildListResponse(req.getSerial(), retList, applyList));
			}
			return;
		}else{
			int maxSize = 50;
			//cache不够数 从数据库取
			List<Guild> retList = name2guildList.get(name);
			if(retList == null){
				retList = new ArrayList<Guild>();
				Object params = DBUtils.wrapParams("name", "%" + name + "%", "limit", 50);
				List<Guild> tmpList = DBUtils.selectList(GuildMapper.STATEMENT_FIND_GUILD_BY_NAME, params);
				maxSize = tmpList.size();
				for(int i = 0; i < maxSize; i++){
					int index = RandomUtils.getRandomNum(0, tmpList.size() - 1);
					Guild remove = tmpList.remove(index);
					Guild cache = gid2guild.get(remove.getId());
					if(cache != null){
						retList.add(cache);
					}else{
						retList.add(remove);
					}
				}
				while(name2guildList.size() >= MAX_CACHE_GUILD_LIST_RESULT){
					String key = name2guildList.keys().nextElement();
					name2guildList.remove(key);
				}
				name2guildList.put(name, retList);
			}
//			//遍历一下 如果公会已经被解散了就remove
//			for(int i = retList.size() - 1; i > -1; i--){
//				if(!gid2guild.containsKey(retList.get(i).getId())){
//					retList.remove(i);
//					break;
//				}
//			}
			player.send(new GuildListResponse(req.getSerial(), retList, applyList));
			return;
		}
	}

	@PomeloOP(PomeloRoute.GUILD_TRANSFER)
	protected void requestTransferGuild(Session session, GuildTransferRequest req){
		Player player = session.getClient();
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			if(member.getDuty() != MEMBER_DUTY_TYPE_CHAIRMAN){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_TRANS));
				return;
			}
			if(player.getId() == req.getTargetId()){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_TRANSFER_SELF));
				return;
			}
		}
		long tid = req.getTargetId();
		GuildMember targetMember = pid2member.get(tid);
		if(targetMember == null){
			targetMember = loadGuildMember(tid);
			if(targetMember == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_THIS_MEMBER));
				return;
			}
		}
		if(targetMember.getGuildid() != guild.getId()){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_SAME_GUILD));
			return;
		}
		if(targetMember.getDuty() != MEMBER_DUTY_TYPE_OFFICIAL){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_MUST_BE_OFFIICIAL));
			return;
		}
		Player targetPlayer = App.getApp().getServiceManager().get(PlayerCacheService.class).find(tid);
		if(targetPlayer == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_PLAYER));
			return;
		}
		if(targetPlayer.getVipLvl() < NEED_VIP){
			player.send(new HintResponse(req.getSerial(), MessageFormat.format(MessageConst.GUILD_PLAYER_NEED_VIP, NEED_VIP)));
			return;
		}
		
		new GuildTransferOperation(player, req.getSerial(), member, tid, 60000, MessageFormat.format(MessageConst.GUILD_TRANSFER_CONFIRM, targetPlayer.getName())).send();
	}
	
	@PomeloOP(PomeloRoute.GUILD_KICK)
	protected void requestKickMember(Session session, GuildKickRequest req){
		Player player = session.getClient();
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			if(member.getDuty() < MEMBER_DUTY_TYPE_OFFICIAL){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_KICK));
				return;
			}
			if(player.getId() == req.getTargetId()){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_KICK_SELF));
				return;
			}
		}
		long tid = req.getTargetId();
		GuildMember targetMember = pid2member.get(tid);
		if(targetMember == null){
			targetMember = loadGuildMember(tid);
			if(targetMember == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_THIS_MEMBER));
				return;
			}
		}
		if(targetMember.getDuty() >= member.getDuty()){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_KICK));
			return;
		}
		if(targetMember.getGuildid() != guild.getId()){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_SAME_GUILD));
			return;
		}
		Player targetPlayer = App.getApp().getServiceManager().get(PlayerCacheService.class).find(tid);
		if(targetPlayer == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_PLAYER));
			return;
		}
		
		targetMember.reset();
		if(gid2guildchannel.containsKey(guild.getId())){
			gid2guildchannel.get(guild.getId()).leave(targetPlayer);
		}
		DBUtils.update(targetMember, GuildMemberMapper.class);
		//公会数量--
		guild.setMemCount(guild.getMemCount() - 1);
		//移出缓存
		tryRemoveFromMemberListCache(guild.getId(), targetMember.getId());
//		player.send(new HintResponse(req.getSerial(), MessageFormat.format(MessageConst.GUILD_KICK_OK, targetPlayer.getName())));
		player.send(new GuildKickResponse(req.getSerial(), targetMember.getId(), targetPlayer.getName()));
		if(targetPlayer.isOnline()){
			targetPlayer.send(new CustomSync(SyncPush.SYNC_GUILD_INFO, new GuildInfoSync(0, null)));
			targetPlayer.send(new HintResponse(req.getSerial(), MessageConst.GUILD_BE_KICK));
		}
		guild.getGevent().addNewGuildEvents(GuildEvent.EVENT_TYPE_KICK, player.getId(), tid);
		LOG.info("[GUILD_KICK]PID[{}]GID[{}]KICKBY[{}]", tid, guild.getId(), player.getId());
		sendSyncForGuildChannel(player.getId(), guild.getId(), GuildChannel.GUILD_MEMBER_CHANGE_SYNC | GuildChannel.GUILD_EVENT_CHANGE_SYNC | GuildChannel.GUILD_DETAIL_CHANGE_SYNC);
	}

	/**
	 * 升/降权限
	 */
	@PomeloOP(PomeloRoute.GUILD_SET_DUTY)
	protected void requestSetDuty(Session session, GuildSetDutyRequest req){
		Player player = session.getClient();
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		long tid = req.getTargetId();
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			if(member.getDuty() != MEMBER_DUTY_TYPE_CHAIRMAN){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_SET_DUTY));
				return;
			}
			if(player.getId() == tid){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_SET_SELF_DUTY));
				return;
			}
		}
		GuildMember targetMember = pid2member.get(tid);
		if(targetMember == null){
			targetMember = loadGuildMember(tid);
			if(targetMember == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_THIS_MEMBER));
				return;
			}
		}
		if(targetMember.getGuildid() != guild.getId()){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_SAME_GUILD));
			return;
		}
		int type = req.getType();
		if(type == 0){//降
			if(targetMember.getDuty() != MEMBER_DUTY_TYPE_OFFICIAL){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_SET_ERROR_DUTY));
				return;
			}
			targetMember.setDuty(MEMBER_DUTY_TYPE_MEMBER);
		}else if(type == 1){//升
			if(targetMember.getDuty() != MEMBER_DUTY_TYPE_MEMBER){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_SET_ERROR_DUTY));
				return;
			}
			int officalCount = 0;
			List<GuildMember> list = getMemberList(guild.getId());
			for(int i = 0, size = list.size(); i < size; i++){
				if(list.get(i).getDuty() == MEMBER_DUTY_TYPE_OFFICIAL){
					officalCount++;
				}
			}
			if(officalCount >= MAX_OFFICIAL_COUNT){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_MAX_OFFICIAL));
				return;
			}
			targetMember.setDuty(MEMBER_DUTY_TYPE_OFFICIAL);
		}else{
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_SET_ERROR_DUTY));
			return;
		}
		if(targetMember.getDuty() == MEMBER_DUTY_TYPE_OFFICIAL){
			guild.getGevent().addNewGuildEvents(GuildEvent.EVENT_TYPE_SET_DUTY_OFFICIAL, player.getId(), tid);
		}else{
			guild.getGevent().addNewGuildEvents(GuildEvent.EVENT_TYPE_SET_DUTY_MEMBER, player.getId(), tid);
		}
		
		player.send(new GuildSetDutyResponse(req.getSerial(), tid, getClientDuty(targetMember.getDuty())));
		LOG.info("[GUILD_SETDUTY]PID[{}]GID[{}]SETBY[{}]DUTY[{}]", tid, guild.getId(), player.getId(), targetMember.getDuty());
		sendSyncForGuildChannel(player.getId(), guild.getId(), GuildChannel.GUILD_MEMBER_CHANGE_SYNC | GuildChannel.GUILD_EVENT_CHANGE_SYNC);
		
		Player targetPlayer = App.getApp().getServiceManager().get(PlayerService.class).getOnlinePlayer(targetMember.getId());
		if(targetPlayer != null){
			targetPlayer.send(new IntSync(SyncPush.SYNC_GUILD_UI_STATE, GuildChannel.GUILD_DETAIL_CHANGE_SYNC));
		}
		
	}

	@PomeloOP(PomeloRoute.GUILD_MEMBER_LIST)
	protected void requestMemberList(Session session, GuildMemberListRequest req){
		Player player = session.getClient();
		GuildMember member = getGuildMember(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
		}
		
		List<GuildMember> retList = getMemberList(guild.getId());
		player.send(new GuildMemberListResponse(req.getSerial(), retList));
	}
	
	@PomeloOP(PomeloRoute.GUILD_EVENT_LIST)
	protected void requestEventList(Session session, GuildEventListRequest req){
		Player player = session.getClient();
		GuildMember member = getGuildMember(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
		}
		List<GuildEvent> events = guild.getGevent().getEvents();
		player.send(new GuildEventListResponse(req.getSerial(), events));
	}

	@PomeloOP(PomeloRoute.GUILD_VIEW_REWARD)
	protected void requestViewReward(Session session, GuildViewRewardRequest req){
		Player player = session.getClient();

		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
		}
		int today = TimeUpdater.getInstance().today();
		int state = 0;
		if(member.getLastGetDay() >= today){
			state = 1;
		}
		
		int vipLvl = player.getVipLvl();
		int duty = member.getDuty();
		int pLvl = player.getLevel();
		int gLvl = exp2level(guild.getExp());
		int money = getRewardMoney(gLvl, pLvl, duty, vipLvl);
		player.send(new GuildViewRewardResponse(req.getSerial(), money, state, vipAdd(vipLvl)));
	}

	@PomeloOP(PomeloRoute.GUILD_GET_REWARD)
	protected void requestGetReward(Session session, GuildGetRewardRequest req){
		Player player = session.getClient();

		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
		}
		int today = TimeUpdater.getInstance().today();
		if(member.getLastGetDay() >= today){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_GET_NOT_TODAY));
			return;
		}
		
		int vipLvl = player.getVipLvl();
		int duty = member.getDuty();
		int pLvl = player.getLevel();
		int gLvl = exp2level(guild.getExp());
		int money = getRewardMoney(gLvl, pLvl, duty, vipLvl);
		player.addGold(money, Cause.GUILD);
		member.setLastGetDay(today);
		player.send(new GuildGetRewardResponse(req.getSerial(), money, 1));
		LOG.info("[GUILD_GET]PID[{}]GID[{}]MONEY[{}]", player.getId(), guild.getId(), money);
	}

	@PomeloOP(PomeloRoute.GUILD_NET_GUILD)
	protected void requestViewNetGuild(Session session, ViewNetGuildRequest req){
		Player player = session.getClient();
		long guildId = req.getGuildId();
		Guild guild = findGuildById(guildId);
		if(guild == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_GUILD));
			return;
		}
		int lvl = exp2level(guild.getExp());
		player.send(new ViewNetGuildResponse(req.getSerial(), guild, lvl));
	}

	@PomeloOP(PomeloRoute.GUILD_DETAIL)
	protected void requestViewGuildDetail(Session session, GuildDetailRequest req){
		Player player = session.getClient();
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
		}
		int[] infos = calcLvlInfo(guild.getExp());
		player.send(new GuildDetailResponse(req.getSerial(), guild, infos[0], infos[1], infos[2], member));
	}
	
	@PomeloOP(PomeloRoute.GUILD_SET_ALL)
	protected void requestSetAll(Session session, GuildSetAllRequest req){
		Player player = session.getClient();
		int joinType = req.getJoinType();
		int joinLvl = req.getJoinLvl();
		if(joinLvl >= JOIN_LEVEL_LIMITS.length || joinLvl < 0){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_JOIN_LVL_ERR));
			return;
		}
		if(joinType != Guild.JOIN_TYPE_FREE && joinType != Guild.JOIN_TYPE_NONE_SHALL_PASS && joinType != Guild.JOIN_TYPE_NEED_APPLY){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_SET_WRONG_TYPE));
			return;
		}
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			if(member.getDuty() != MEMBER_DUTY_TYPE_CHAIRMAN){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NO_RIGHT_TO_SET));
				return;
			}
		}
		int type1 = req.getType1();
		int type2 = req.getType2();
		guild.setFlag(type1 << 8 | type2);
		guild.setJoinLvl((byte) joinLvl);
		guild.setJoinType((byte) joinType);
		player.send(new GuildSetAllResponse(req.getSerial(), joinType, type1, type2, joinLvl));
		LOG.info("[GUILD_SET]PID[{}]GID[{}]JOINTYPE[{}]ICON[{}]", player.getId(), guild.getId(), joinType, guild.getFlag(), joinLvl);

		//其他成员同步
		sendSyncForGuildChannel(player.getId(), guild.getId(), GuildChannel.GUILD_DETAIL_CHANGE_SYNC);
	}
	
	@PomeloOP(PomeloRoute.GUILD_VIEW_DONATE)
	protected void requestViewDonate(Session session, GuildViewDonateRequest req){
		Player player = session.getClient();
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
		}

		int[] infos = calcLvlInfo(guild.getExp());
		List<GuildDonateTemplate> list = App.getApp().getServiceManager().get(TemplateService.class).getTemplatesList(GuildDonateTemplate.class);
		player.send(new GuildViewDonateResponse(req.getSerial(), guild, infos[0], infos[1], infos[2], list, member));
	}

	@PomeloOP(PomeloRoute.GUILD_DONATE)
	protected void requestDonate(Session session, GuildDonateRequest req){
		Player player = session.getClient();
		GuildMember member = pid2member.get(player.getId());
		Guild guild = null;
		if(member == null){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
			return;
		}else{
			if(member.getGuildid() <= 0){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
			guild = findGuildById(member.getGuildid());
			if(guild == null){
				player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_NOT_IN_GUILD));
				return;
			}
		}
		int type = req.getType();
		int today  = TimeUpdater.getInstance().today();
		GuildDonateTemplate temp = type2donateTemp.get(req.getType());
		if(temp == null || temp.getMax() <= 0){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_GET_DONATE_WRONG_TYPE));
			return;
		}
		int doCount = member.getMemData().getDonateCountToday(type, today);
		if(doCount < 0){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_GET_DONATE_WRONG_TYPE));
			return;
		}
		
		int leftCount = temp.getMax() - doCount;
		if(leftCount < 1){
			player.send(new HintResponse(req.getSerial(), MessageConst.GUILD_DONATE_NEED_COUNT));
			return;
		}
		if(player.getVipLvl() < temp.getNeedvip()){
			player.send(new HintResponse(req.getSerial(), MessageFormat.format(MessageConst.GUILD_DONATE_NEED_VIP, temp.getNeedvip())));
			return;
		}
		
		if(temp.getStone() > 0){
			if(!player.costStone(temp.getStone(), Cause.GUILD_DONATE)){
				return;
			}
		}
		player.addGuildScore(temp.getScore(), Cause.GUILD_DONATE);
		if(!checkIsMaxLvl(guild.getExp())){
			guild.addExp(temp.getExp(), Cause.GUILD_DONATE);
		}
		int newDoCount = member.getMemData().addDonateCountToday(type, today);
		leftCount = temp.getMax() - newDoCount;
		if(leftCount < 0){
			leftCount = 0;
		}
		
		int[] infos = calcLvlInfo(guild.getExp());
		player.send(new GuildDonateResponse(req.getSerial(), type, infos[0], infos[1], infos[2], leftCount));
		//其他成员同步
		sendSyncForGuildChannel(player.getId(), guild.getId(), GuildChannel.GUILD_DETAIL_CHANGE_SYNC);
	}
	
	private int getRewardMoney(int gLvl, int pLvl, int duty, int vipLvl){
		//TODO
		int dutyAdd = 0;
		if(duty == MEMBER_DUTY_TYPE_CHAIRMAN){
			dutyAdd = 50;
		}else if(duty == MEMBER_DUTY_TYPE_OFFICIAL){
			dutyAdd = 20;
		}
		long ret = ((long)BASE_REWARD) * gLvl * (100 + dutyAdd) * (vipAdd(vipLvl) + 100);
		
		int money = (int) (ret / 10000L);
		return money;
	}
	
	private int vipAdd(int vipLvl){
		return vipLvl * 10;
	}
	
	public List<GuildMember> getMemberList(long guildId){
		List<GuildMember> retList = gid2memberList.get(guildId);
		if(retList == null){
			retList = new ArrayList<GuildMember>();
			List<GuildMember> tmpList = DBUtils.selectList(GuildMemberMapper.STATEMENT_FIND_BY_GUILD, guildId);
			for(int i = 0, size = tmpList.size(); i < size; i++){
				GuildMember dbMember = tmpList.get(i);
				GuildMember cacheMember = getGuildMember(dbMember.getId());
				if(cacheMember != null){
					retList.add(cacheMember);
				}else{
					retList.add(dbMember);
				}
			}
			while(gid2memberList.size() >= MAX_CACHE_MEMBER_LIST_RESULT){
				long key = gid2memberList.keys().nextElement();
				gid2memberList.remove(key);
			}
			gid2memberList.put(guildId, retList);
		}
		return retList;
	}
	
	/**
	 * 检查公会名是否合法
	 * @return 错误信息或null
	 */
	private String checkGuildName(String name){
		if(StringUtils.isEmpty(name)){
			return MessageConst.GUILD_NAME_EMPTY;
		}
		if(StringUtils.getStrLength(name) > GUILD_NAME_LENGTH){
			return MessageConst.GUILD_NAME_TOO_LONG;
		}
		if(badwordsFilter != null && badwordsFilter.containsBadWord(name)){
			return MessageConst.GUILD_NAME_INVALID;
		}
		int count = DBUtils.select(GuildMapper.STATEMENT_COUNT_GUILD_BY_NAME, name);
		if(count > 0){
			return MessageConst.GUILD_NAME_SAME;
		}
		return null;
	}

	/**
	 * 公告名是否合法
	 * @return 错误信息或null
	 */
	private String checkSlogan(String slogan){
		if(StringUtils.getStrLength(slogan) > GUILD_SLOGAN_LENGTH){
			return MessageFormat.format(MessageConst.GUILD_SLOGAN_TOO_LONG, GUILD_SLOGAN_LENGTH);
		}
		return null;
	}
	
	public void toDisbandLog(long pid, long gid){
		LOG.info("[GUILD_DISBAND]PID[{}]GID[{}]", pid, gid);
	}
	
	public void toTransLog(long pid, long gid, long newchairman){
		LOG.info("[GUILD_TRANS]PID[{}]GID[{}]NEWCHAIRMAN[{}]", pid, gid, newchairman);
	}
	
	/**
	 * 移除公会频道
	 */
	public void removeGuildChannel(long gid){
		if(gid2guildchannel.containsKey(gid)){
			gid2guildchannel.remove(gid);
		}
	}
	/**
	 * 发送公会聊天消息
	 */
	public void sendPushForGuildChannel(ChatMessage chat, ChatPush push){
		long gid = chat.getDestId();
		if(gid2guildchannel.containsKey(gid)){
			gid2guildchannel.get(gid).broadcast(chat.getSrcId(), push);
		}
	}
	
	/**
	 * 发送同步信息
	 * @param pid 操作者的id
	 * @param gid 发生变化公会的id
	 * @param state 状态值 {@GuildChannel}
	 */
	public void sendSyncForGuildChannel(long pid, long gid, int state){
		//其他成员同步
		GuildChannel chn = gid2guildchannel.get(gid);
		if(chn != null){
			chn.sendSync(pid, new IntSync(SyncPush.SYNC_GUILD_UI_STATE, state));
		}
	}
	
	public int exp2level(int exp){
		int level = 1;
		for(int i = guildTotalExp.length - 1; i > -1; i--){
			if(exp >= guildTotalExp[i]){
				level = i + 2;
				break;
			}
		}		
		return level;
	}
	
	/**
	 * 计算等级经验信息
	 * @param 公会的总经验
	 * @return {当前等级, 当前经验, 当前等级最大经验}
	 */
	public int[] calcLvlInfo(int curTotalExp){
		int[] infos = new int[]{1, 0, 0};

		int lvl = exp2level(curTotalExp);
		int min = 0;
		int max = 0;
		int showCur = 0;
		int showNeed = 0;
		if(lvl > 0){
			if(lvl > 1){
				min = guildTotalExp[lvl - 2];//升到lvl-2+2级需要的总经验
			}
			if(guildTotalExp.length < lvl){
				min = guildTotalExp[lvl - 3];
				max = guildTotalExp[lvl - 2];
				showCur = max - min;
				showNeed = max - min;
			}else{
				max = guildTotalExp[lvl - 1];//升到lvl-1+2级需要的总经验
				showCur = curTotalExp - min;
				showNeed = max - min;
			}
		}
		infos[0] = lvl;
		infos[1] = showCur;
		infos[2] = showNeed;
		return infos;
	}
	
	public boolean checkIsMaxLvl(int curTotalExp){
		int lvl = exp2level(curTotalExp);
		if(guildTotalExp.length < lvl){
			return true;
		}
		return false;
	}
	
	public int getJoinNeedLvlByGuild(Guild guild){
		int lvlLimit = 0;
		if(guild != null){
			byte joinLvl = guild.getJoinLvl();
			if(joinLvl < JOIN_LEVEL_LIMITS.length && joinLvl > -1){
				lvlLimit = JOIN_LEVEL_LIMITS[joinLvl];
			}
		}
		return lvlLimit;
	}
	
	public static int getClientDuty(int duty){
		int ret = 0;
		if(duty == MEMBER_DUTY_TYPE_CHAIRMAN){
			ret = 2;
		}else if(duty == MEMBER_DUTY_TYPE_OFFICIAL){
			ret = 1;
		}
		return ret;
	}

	@Override
	public boolean update() {
		long now = TimeUpdater.getInstance().now();
		if(now - lastPrintCacheSize > 900000){
			lastPrintCacheSize = now;
			//15分钟打印一次cache数
			LOG.info("[GUILD_PRINT]GUILDS[{}]MEMBERS[{}]", gid2guild.size(), pid2member.size());
		}
		return true;
	}
}
